package com.hgkj.cloud.customer.util;

import java.awt.image.BufferedImage;


import com.hgkj.cloud.customer.common.ResponseData;
import com.spire.doc.Document;
import com.spire.doc.FileFormat;
import com.spire.doc.HeaderFooter;
import com.spire.doc.Section;
import com.spire.doc.TextWatermark;
import com.spire.doc.documents.Paragraph;
import com.spire.doc.documents.ShapeLineStyle;
import com.spire.doc.documents.ShapeType;
import com.spire.doc.documents.WatermarkLayout;
import com.spire.doc.fields.ShapeObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ooxml.POIXMLDocument;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.sl.usermodel.PictureData;
import org.apache.poi.sl.usermodel.PictureData.PictureType;
import org.apache.poi.xslf.usermodel.*;
import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFHeader;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;

import javax.imageio.ImageIO;
import java.awt.Color;
import java.awt.Font;
import java.awt.*;
import java.awt.Image;
import java.awt.font.FontRenderContext;
import java.awt.geom.Rectangle2D;
import java.io.*;


/**
 * @Author:      添加水印 utils
 * @Date: 2023/2/24
**/
@Slf4j
public class WaterMarkUtil {
    // 水印透明度
    private static float alpha = 0.5f;
    // 水印之间的间隔
    private static final int XMOVE = 200;
    // 水印之间的间隔
    private static final int YMOVE = 200;

    public static void main(String[] args) {
        addPictureWaterMark("d:/tmp/love.jpg", "d:/tmp/love.png", "我是水印");
        setPictureWatermark("d:/tmp/love.jpg", "d:/tmp/love.png", Color.GRAY, "我是水印");
        setWordWaterMark("d:/tmp/love.docx", "d:/tmp/love1.docx", "我是水印", "docx");
        setPPTWaterMark("d:/tmp/love.pptx", "d:/tmp/love1.pptx", "我是水印");
    }

    /**
     * @param srcImgPath       源图片路径
     * @param tarImgPath       保存的图片路径
     * @param waterMarkContent 水印内容
     */
    public static void addPictureWaterMark(String srcImgPath, String tarImgPath,
                                           String waterMarkContent) {
        FileOutputStream outImgStream = null;
        try {
            // 读取原图片信息
            File srcImgFile = new File(srcImgPath);// 得到文件
            Image srcImg = ImageIO.read(srcImgFile);// 文件转化为图片
            int srcImgWidth = srcImg.getWidth(null);// 获取图片的宽
            int srcImgHeight = srcImg.getHeight(null);// 获取图片的高
            // 加水印
            BufferedImage bufImg = new BufferedImage(srcImgWidth, srcImgHeight,
                    BufferedImage.TYPE_INT_RGB);
            Graphics2D g = bufImg.createGraphics();
            // 设置对线段的锯齿状边缘处理
            g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                    RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            g.drawImage(srcImg, 0, 0, srcImgWidth, srcImgHeight, null);
            // 设置水印旋转
            g.rotate(Math.toRadians(-40),
                    (double) bufImg.getWidth() / 2,
                    (double) bufImg.getHeight() / 2);
            g.setColor(new Color(107, 109, 106)); // 根据图片的背景设置水印颜色
            Font font = new Font("宋体", Font.PLAIN, 20);
            g.setFont(font); // 设置字体
            // 设置水印文字透明度
//			g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP,alpha));

            //根据不同的像素判断多个水印还是单个水印300*300
            if (srcImgWidth > 300 && srcImgHeight > 300) {
                //多个水印
                // 设置水印的坐标
                int x = -srcImgWidth / 2;
                int y = -srcImgHeight / 2;
                int markWidth = font.getSize() * getTextLength(waterMarkContent);// 字体长度
                int markHeight = font.getSize();// 字体高度
                // 循环添加水印
                while (x < srcImgWidth * 1.5) {
                    y = -srcImgHeight / 2;
                    while (y < srcImgHeight * 1.5) {
                        g.drawString(waterMarkContent, x, y);
                        y += markHeight + YMOVE;
                    }
                    x += markWidth + XMOVE;
                }
            } else {
                //单个水印
                int x = (srcImgWidth - getWatermarkLength(waterMarkContent, g)) / 2;
                int y = srcImgHeight / 2;
                g.drawString(waterMarkContent, x, y);
            }
            g.dispose();
            // 输出图片
            outImgStream = new FileOutputStream(tarImgPath);
            String formatName = srcImgPath.substring(srcImgPath.lastIndexOf(".") + 1, srcImgPath.length());
            ImageIO.write(bufImg, formatName, outImgStream);
            outImgStream.flush();
        } catch (Exception e) {
            log.error("addPictureWatermark fail", e);
            ResponseData.getResponseData(-1, "addPictureWatermark fail");
        } finally {
            if (outImgStream != null) {
                try {
                    outImgStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 图片添加水印
     *
     * @param srcImgPath       需要添加水印的图片的路径
     * @param outImgPath       添加水印后图片输出路径
     * @param markContentColor 水印文字的颜色
     * @param waterMarkContent 水印的文字
     */
    public static void setPictureWatermark(String srcImgPath, String outImgPath, Color markContentColor, String waterMarkContent) {
        FileOutputStream outImgStream = null;
        try {
            // 读取原图片信息
            File srcImgFile = new File(srcImgPath);
            Image srcImg = ImageIO.read(srcImgFile);
            int srcImgWidth = srcImg.getWidth(null);
            int srcImgHeight = srcImg.getHeight(null);
            // 加水印
            BufferedImage bufImg = new BufferedImage(srcImgWidth, srcImgHeight, BufferedImage.TYPE_INT_RGB);
            Graphics2D g = bufImg.createGraphics();
            g.drawImage(srcImg, 0, 0, srcImgWidth, srcImgHeight, null);
            Font font = new Font("宋体", Font.BOLD, srcImgHeight / 6);
            //根据图片的背景设置水印颜色
            g.setColor(markContentColor);
            //设置旋转角度
            g.rotate(Math.toRadians(-45), (double) bufImg.getWidth() / 2, (double) bufImg.getHeight() / 2);
            //设置水印透明度
            g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.2F));

            g.setFont(font);
            int x = (srcImgWidth - getWatermarkLength(waterMarkContent, g)) / 2;
            int y = srcImgHeight / 2;
            g.drawString(waterMarkContent, x, y);
            g.dispose();
            // 输出图片
            outImgStream = new FileOutputStream(outImgPath);
            ImageIO.write(bufImg, "jpg", outImgStream);
            outImgStream.flush();
            outImgStream.close();
        } catch (Exception e) {
            log.error("setPictureWatermark fail", e);
            ResponseData.getResponseData(-1, "setPictureWatermark fail");
        } finally {
            if (outImgStream != null) {
                try {
                    outImgStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * word文字水印
     *
     * @param inputPath
     * @param outPath
     * @param markStr
     */
    public static void setWordWaterMark(String inputPath, String outPath, String markStr, String fileType) {
        if ("docx".equals(fileType)) {
            File inputFile = new File(inputPath);
            //2003doc 用HWPFDocument  ； 2007doc 用 XWPFDocument
            XWPFDocument doc = null;
            try {
                OPCPackage pack = POIXMLDocument.openPackage(inputPath);
                doc = new XWPFDocument(pack);
//                doc = new XWPFDocument(new FileInputStream(inputFile));
            } catch (FileNotFoundException e) {
                log.error("setWordWaterMark fail: 源文件不存在", e);

                ResponseData.getResponseData(-1, "setWordWaterMark fail: 源文件不存在");
            } catch (IOException e) {
                log.error("setWordWaterMark fail: 读取源文件IO异常", e);
                ResponseData.getResponseData(-1, "setWordWaterMark fail: 读取源文件IO异常");
            } catch (Exception e) {
                log.error("setWordWaterMark fail: 不支持的文档格式", e);
                ResponseData.getResponseData(-1, "setWordWaterMark fail: 不支持的文档格式");
            }
            XWPFParagraph paragraph = doc.createParagraph();
            XWPFHeaderFooterPolicy headerFooterPolicy = doc.getHeaderFooterPolicy();
            if (headerFooterPolicy == null) {
                headerFooterPolicy = doc.createHeaderFooterPolicy();
            }
            // create default Watermark - fill color black and not rotated
            headerFooterPolicy.createWatermark(markStr);
            // get the default header
            // Note: createWatermark also sets FIRST and EVEN headers
            // but this code does not updating those other headers
            XWPFHeader header = headerFooterPolicy.getHeader(XWPFHeaderFooterPolicy.DEFAULT);
            paragraph = header.getParagraphArray(0);
//            // get com.microsoft.schemas.vml.CTShape where fill color and rotation is set
//            paragraph.getCTP().newCursor();
//            System.out.println(paragraph.getCTP().getRArray(0));
//            System.out.println(paragraph.getCTP().getRArray(0).getPictArray(0));
            org.apache.xmlbeans.XmlObject[] xmlobjects = paragraph.getCTP().getRArray(0).getPictArray(0).selectChildren(
                    new javax.xml.namespace.QName("urn:schemas-microsoft-com:vml", "shape"));
            if (xmlobjects.length > 0) {
                com.microsoft.schemas.vml.CTShape ctshape = (com.microsoft.schemas.vml.CTShape) xmlobjects[0];
                ctshape.setFillcolor("#D3D3D3");
                ctshape.setStyle(ctshape.getStyle() + ";rotation:315" + ";height:60pt;width:360pt");
            }
            File file = new File(outPath);
            if (!file.exists()) {
                try {
                    file.createNewFile();
                } catch (IOException e) {
                    log.error("setWordWaterMark fail: 创建输出文件IO异常", e);
                    ResponseData.getResponseData(-1, "setWordWaterMark fail: 创建输出文件失败");
                }
            }
            try {
                doc.write(new FileOutputStream(outPath));
            } catch (FileNotFoundException e) {
                log.error("setWordWaterMark fail: 输出文件不存在", e);
                ResponseData.getResponseData(-1, "setWordWaterMark fail: 创建输出文件失败");

            } catch (IOException e) {
                log.error("setWordWaterMark fail: ", e);
                ResponseData.getResponseData(-1, "setWordWaterMark fail");
            } finally {
                if (doc != null) {
                    try {
                        doc.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }


    /**
     * PPT设置水印
     *
     * @param path
     * @param targetpath
     * @param markStr
     * @throws IOException
     */
    public static void setPPTWaterMark(String path, String targetpath, String markStr) {
        XMLSlideShow slideShow = null;
        try {
            slideShow = new XMLSlideShow(new FileInputStream(path));
        } catch (IOException e) {
            log.error("setPPTWaterMark fail:", e);
            //  throw new MyException(ResultCode.FAILURE, "setPPTWaterMark fail:获取PPT文件失败");
            ResponseData.getResponseData(-1, "setPPTWaterMark fail:获取PPT文件失败");
        }
        ByteArrayOutputStream os = null;
        FileOutputStream out = null;
        try {
            //获取水印
            os = getImage(markStr);
            PictureData pictureData1 = slideShow.addPicture(os.toByteArray(), PictureType.PNG);
            for (XSLFSlide slide : slideShow.getSlides()) {
                XSLFPictureShape pictureShape = slide.createPicture(pictureData1);
//                pictureShape.setAnchor(new java.awt.Rectangle(250, 0, 500, 500));
                pictureShape.setAnchor(pictureShape.getAnchor());
            }
            out = new FileOutputStream(targetpath);
            slideShow.write(out);
        } catch (IOException e) {
            log.error("setPPTWaterMark fail:" + e);
            ResponseData.getResponseData(-1, "setPPTWaterMark fail：生成ppt文件失败");
        } finally {
            if (slideShow != null) {
                try {
                    slideShow.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 获取水印文字总长度
     *
     * @param waterMarkContent 水印的文字
     * @param g
     * @return 水印文字总长度
     */
    public static int getWatermarkLength(String waterMarkContent, Graphics2D g) {
        return g.getFontMetrics(g.getFont()).charsWidth(waterMarkContent.toCharArray(), 0, waterMarkContent.length());
    }

    /**
     * 获取文本长度。汉字为1:1，英文和数字为2:1
     */
    private static int getTextLength(String text) {
        int length = text.length();
        for (int i = 0; i < text.length(); i++) {
            String s = String.valueOf(text.charAt(i));
            if (s.getBytes().length > 1) {
                length++;
            }
        }
        length = length % 2 == 0 ? length / 2 : length / 2 + 1;
        return length;
    }

    /**
     * 获取水印文字图片流
     *
     * @param text
     * @return
     */
    private static ByteArrayOutputStream getImage(String text) {
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        try {
            // 导出到字节流B
            BufferedImage image = createWaterMarkImageBig(text);
            ImageIO.write(image, "png", os);
        } catch (IOException e) {
            log.error("getImage fail: 创建水印图片IO异常", e);
            ResponseData.getResponseData(-1, "getImage fail: 创建水印图片IO异常");
        }
        return os;
    }

    /**
     * 根据文字生成水印图片（大号 平铺）
     *
     * @param text
     * @return
     */
    public static BufferedImage createWaterMarkImageBig(String text) {
        Integer width = 1000;
        Integer height = 800;
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);// 获取bufferedImage对象
        Font font = new Font("宋体", Font.PLAIN, 70);
        Graphics2D g2d = image.createGraphics();
        image = g2d.getDeviceConfiguration().createCompatibleImage(width, height, Transparency.TRANSLUCENT);
        g2d.dispose();
        g2d = image.createGraphics();
        //设置字体颜色和透明度
        g2d.setColor(new Color(0, 0, 0, 60));
        //设置字体
        g2d.setStroke(new BasicStroke(1));
        //设置字体类型  加粗 大小
        g2d.setFont(font);
        //设置倾斜度
        g2d.rotate(Math.toRadians(-30), (double) image.getWidth() / 2, (double) image.getHeight() / 2);
        FontRenderContext context = g2d.getFontRenderContext();
        Rectangle2D bounds = font.getStringBounds(text, context);
        double x = (width - bounds.getWidth()) / 2;
        double y = (height - bounds.getHeight()) / 2;
        double ascent = -bounds.getY();
        double baseY = y + ascent;
        //写入水印文字原定高度过小，所以累计写水印，增加高度
        g2d.drawString(text, (int) x, (int) baseY);
        //设置透明度
        g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
        //释放对象
        g2d.dispose();
        return image;
    }

    public static void InsertTextWatermark(Section section,String markStr){
        TextWatermark txtWatermark = new TextWatermark();
        txtWatermark.setText(markStr);
        txtWatermark.setFontSize(40);
        txtWatermark.setColor(Color.BLACK);
        txtWatermark.setLayout(WatermarkLayout.Diagonal);
        section.getDocument().setWatermark(txtWatermark);
    }

    /**
     * 输入流,加水印后输出
     *
     *
     * @param type 控制输出文件类型
     * @param waterName 显示水印文字内容
     */
    public static void docWaterMark(String  inputPath, String  outPath,int type,String waterName) throws FileNotFoundException {
        InputStream stream=null;
        OutputStream outputStream=null;
        try {
         stream = new FileInputStream(inputPath);
         outputStream = new FileOutputStream(outPath);
        Document document = new Document();
        if (0 == type) {
            document.loadFromStream(stream, FileFormat.Doc);
            InsertTextWatermark(document.getSections().get(0),waterName);
            document.saveToStream(outputStream, FileFormat.Doc);
        } else if (1 == type){
            document.loadFromStream(stream, FileFormat.Docx);
            InsertTextWatermark(document.getSections().get(0),waterName);
            document.saveToStream(outputStream, FileFormat.Docx);
            File file=new File(inputPath);
            if(file.exists()){
                file.delete();
            }
        }
        outputStream.flush();
            outputStream.close();
        } catch (IOException e) {
            log.error(e.getMessage(),e);
        }finally {
            try {
                if (outputStream != null) {
                    outputStream.close();
                }
            } catch (Exception e) {
                log.error(e.getMessage(),e);
            }
        }
    }

    /**
     *    多个水印
     * @param sample
     * @param result
     * @param markStr
     */

    public static void addMarkStr(String sample,String result,String markStr){
        //加载示例文档
        Document doc = new Document();
        doc.loadFromFile(sample);
        //添加艺术字并设置大小
        ShapeObject shape = new ShapeObject(doc, ShapeType.Text_Plain_Text);
        shape.setWidth(60);
        shape.setHeight(20);
        //设置艺术字文本内容、位置及样式
        shape.setVerticalPosition(30);
        shape.setHorizontalPosition(20);
        shape.setRotation(315);
        shape.getWordArt().setFontFamily("黑体");
        shape.getWordArt().setText(markStr);
        shape.setFillColor(Color.BLACK);
        shape.setLineStyle(ShapeLineStyle.Single);
        shape.setStrokeColor(new Color(192, 192, 192, 255));
        shape.setStrokeWeight(1);

        Section section;
        HeaderFooter header;
        for (int n = 0; n < doc.getSections().getCount(); n++) {
            section = doc.getSections().get(n);
            //获取section的页眉
            header = section.getHeadersFooters().getHeader();
            Paragraph paragraph;

            if (header.getParagraphs().getCount() > 0) {
                //如果页眉有段落，取它第一个段落
                paragraph = header.getParagraphs().get(0);
            } else {
                //否则新增加一个段落到页眉
                paragraph = header.addParagraph();
            }
            for (int i = 0; i < 4; i++) {
                for (int j = 0; j < 3; j++) {
                    //复制艺术字并设置多行多列位置
                    shape = (ShapeObject) shape.deepClone();
                    shape.setVerticalPosition(50 + 150 * i);
                    shape.setHorizontalPosition(20 + 160 * j);
                    paragraph.getChildObjects().add(shape);
                }
            }
        }
        //保存文档
        doc.saveToFile(result, FileFormat.Docx_2013);
    //删除原先的文件
        File file=new File(sample);
        if(file.exists()){
            file.delete();
        }
}





}
